/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#ifndef INCLUDE_SHADER_PBR_FUNCTIONS
#define INCLUDE_SHADER_PBR_FUNCTIONS


#include "shader_binding_ID.h"
#include "shader_built_in_functions.h"
#include "shader_std.h"
#include "shader_ray.h"


#ifdef __cplusplus

//#include <基本类型.h>

using uint = unsigned int;

#define in
#define out
#define inout



Inline S_Material f_material_init() {
	S_Material rayMaterial{};
	rayMaterial.m_color = { 1.0f, 0.0f, 0.8f };
	rayMaterial.m_colorTex = -1;

	rayMaterial.m_emission = {};				//发光
	rayMaterial.m_emissionTex = -1;

	rayMaterial.m_specular = {1,1,1};
	rayMaterial.m_specularTex = -1;


	rayMaterial.m_reflect = 0;					//反射度
	rayMaterial.m_reflectTex = -1;

	rayMaterial.m_refract = 0;					//折射
	rayMaterial.m_refractTex = -1;

	rayMaterial.m_roughness = 0.5;				//粗糙度
	rayMaterial.m_roughnessTex = -1;

	rayMaterial.m_alpha = 1;
	rayMaterial.m_alphaTex = -1;

	

	rayMaterial.m_normalTex = -1;


	rayMaterial.m_transmission = 0;


	rayMaterial.m_shaderIndex = -1;
	rayMaterial.m_LigthMask = 1;


	rayMaterial.m_CustomAttrOffset = 0;

	return rayMaterial;
}




#else

#define Inline

vec3 f_MaterialPBR_calc(in S_Material material, in vec3 RayDirection, in S_SceneDataCall hitValue) {
	float metallic = 0.8;
	//float roughness = material.m_roughness;
	float roughness = 0.5;
	vec3 F0 = vec3(0.04);
	//return F0;
	//vec3 albedo = (material.m_color) * hitValue.irradiance;
	//vec3 albedo = vec3(material.m_color_r, material.m_color_g, material.m_color_b);
	//vec3 albedo = vec3(1);
	//albedo = vec3(0, 0, 0);
	//return vec3(material.m_color);
	vec3 albedo = material.m_color;// * hitValue.irradiance;

	vec3 V = RayDirection;
	vec3 H = normalize(V - hitValue.ligthDir);

	//float denom = 4 * max(dot(hitValue.Normal, V), 0) * max(dot(hitValue.Normal, LigthDir), 0.0) + 0.0001;
	float NDF = f_DistributionGGX(hitValue.Normal, H, roughness);
	//return albedo * NDF;


	F0 = mix(F0, albedo, metallic);
	vec3 F = f_fresnelSchlick(max(dot(H, V), 0), F0);
	
	vec3 KD = vec3(1) - F;
	KD *= 1.0 - metallic;
	
	float G = f_GeometrySmith(hitValue.Normal, (V), hitValue.ligthDir, roughness);
	//return vec3(F);
	
	vec3 numerator = NDF * F * G;
	
	
	//float denominator = float(hitValue.Depth) * max(dot(hitValue.Normal, V), 0.0) * max(dot(hitValue.Normal, LigthDir), 0.0) + 0.0001;
	float denominator = 1.0 * max(dot(hitValue.Normal, V), 0.0) * max(dot(hitValue.Normal, hitValue.ligthDir), 0.0) + 0.0001;
	vec3 specular = numerator / denominator;
	//hitValue.Color = vec3(hitValue.irradiance);
	//return vec3(specular);

	float NdotL = max(dot(hitValue.Normal, hitValue.ligthDir), 0);
	vec3 Color = (KD * albedo / M_PI + specular) * NdotL;
	
	Color = F0 * albedo + Color;// * hitValue.irradiance;
	//Color = albedo + Color;// *hitValue.irradiance; * hitValue.irradiance
	//Color = material.m_color;
	//return vec3(1,0,0);
	//material.m_roughness = NDF;
	return Color;
}





//双向反射分布函数：计算 Cook-Torrance Microfacet BRDF
Inline vec3 cookTorranceBRDF(in S_Material material, in vec3 RayDirection, in S_SceneDataCall hitValue) {
	// 计算几何遮蔽项
	float NdotL = max(dot(hitValue.Normal, hitValue.ligthDir), 0.0);
	float NdotV = max(dot(hitValue.Normal, RayDirection), 0.0);
	float NdotH = max(dot(hitValue.Normal, normalize(hitValue.ligthDir + RayDirection)), 0.0);

	//计算粗糙度相关的系数
	float roughnessSq = material.m_roughness * material.m_roughness;
	float roughnessSqD = roughnessSq * (1.0 - material.m_reflect);

	//计算分布函数（Distribution Function）
	float D = exp((NdotH * NdotH - 1.0) / (roughnessSqD * NdotH * NdotH));

	//计算菲涅耳反射（Fresnel Reflectance）：
	float F = material.m_reflect + (1.0 - material.m_reflect) * pow(1.0 - NdotL, 5.0);

	//计算几何遮蔽（Geometrical Attenuation）
	float G = min(1.0, 2.0 * NdotH * min(NdotV, NdotL) / (NdotL + NdotV));

	//将分布函数、菲涅耳反射和几何遮蔽相乘，并除以视角方向与法线的点乘和光线方向与法线的点乘的乘积
	//return (D * F * G) / (3.14159265359 * NdotV * NdotL);

	//计算高光强度
	//float specularIntensity = pow(max(1.0 - dot(normalize(hitValue.ligthDir + RayDirection), hitValue.Normal), 0.0), material.m_specular);
	vec3 specular = vec3((F * G * D) / (4.0f * NdotV)) * material.m_specular;
	vec3 diffuse = (vec3(1.0f) - F) * (1.0f - material.m_reflect);
	//return (F * G * D * specularIntensity) / max(4.0 * NdotV * NdotL, 0.001);
	//return (F * G * D) / max(4.0 * NdotV * NdotL, 0.001) + (specularIntensity );
	return specular + diffuse;
}



#endif


//���߷ֲ���
Inline float f_SpecularDistribution(in vec3 N, in vec3 H, float roughness) {
    float a2 = roughness * roughness;
    float NdotH = max(dot(N, H), 0.0);
    float NdotH2 = NdotH * NdotH;

    float nom = a2;
    float denom = (NdotH2 * (a2 - 1.0) + 1.0);
    denom = M_PI * denom * denom;

    return nom / denom;
}




// 函数：计算光照
Inline vec3 calculateLighting(in vec3 RayDirection, in S_SceneDataCall hitValue, vec3 viewDir, vec3 albedo, vec3 lightColor, vec3 ambientLight, float metallic, float roughness) {
	vec3 V = RayDirection;
	vec3 H = normalize(V - hitValue.ligthDir);
	
	// 计算漫反射光照分量
	float NdotL = max(dot(hitValue.Normal, hitValue.ligthDir), 0.0);
	vec3 diffuse = albedo * lightColor * NdotL;

	// 计算镜面反射光照分量
	vec3 halfwayDir = normalize(hitValue.ligthDir + viewDir);
	float NdotH = max(dot(hitValue.Normal, halfwayDir), 0.0);
	float roughnessSq = roughness * roughness;
	float d = (2.0 * roughnessSq - 2.0) * (NdotH * NdotH) + 1.0;
	float specular = (roughnessSq / d) * lightColor.x;

	// 计算环境光照分量
	vec3 ambient = ambientLight * albedo;

	// 综合光照分量
	vec3 lighting = (diffuse + specular + ambient) * (1.0 - metallic);

	return lighting;
}


Inline vec3 calculateDiffuse(vec3 albedo) {
	return albedo / 3.14159265359;
}
Inline vec3 computeColor(vec3 baseColor, vec3 specularColor, vec3 reflectionColor, vec3 emissionColor, float brightness) {
	// 计算包含高光颜色在内的颜色
	vec3 color = baseColor * brightness + specularColor + reflectionColor + emissionColor;
	return color;
}




//vec3 calculateSpecular(vec3 F0, vec3 N, vec3 V, vec3 L, float roughness) {
//	vec3 H = normalize(V + L);
//
//	float NdotV = max(dot(N, V), 0.0);
//	float NdotL = max(dot(N, L), 0.0);
//	float NdotH = max(dot(N, H), 0.0);
//	float VdotH = max(dot(V, H), 0.0);
//
//	vec3 F = fresnelSchlickRoughness(VdotH, F0, roughness);
//	float D = distributionGGX(N, H, roughness);
//	float G = geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness);
//
//	vec3 specular = F * (G * D) / (4.0 * NdotV * NdotL + 0.001);
//
//	return specular;
//}



#endif

